#include "Listener.h"
#include "Broady.h"
#include "Application.h"
#include "Socket.h"
#include "External.h"
#include "utils.h"
#include <boost/shared_ptr.hpp>

namespace Broady {

bool Listener::SendPacket( boost::shared_ptr<client_t> client, const char* packet, unsigned int len, unsigned short port )
{
	if( !client || !packet || len == 0 )
	{
		return false;
	}

	ip_address ipaddr = *reinterpret_cast<ip_address*>( &client->node_ip );

	OutputMessage( "Listener >> Transmitting broadcast to %u.%u.%u.%u:%u\n", ipaddr.byte1, ipaddr.byte2, ipaddr.byte3, ipaddr.byte4, port );

	if( !client->node->SendTo( packet, len, client->node_ip, port ) )
	{
		return false;
	}

	return true;
}

bool Listener::SendBroadcast( boost::shared_ptr<client_t> client, const char* packet, unsigned int len, unsigned short port )
{
	if( !client || !packet || len == 0 )
	{
		return false;
	}

	OutputMessage( "Listener >> Transmitting broadcast to 255.255.255.255:%u\n", port );

	if( !client->node->SendTo( packet, len, 0xFFFFFFFF, port ) )
	{
		return false;
	}

	return true;
}

bool Listener::Parse( boost::shared_ptr<client_t> client, boost::shared_ptr<unsigned char> packet, unsigned int len, unsigned long ip, unsigned short port )
{
	if( len == 0 )
	{
		return false;
	}

	return g_App->GetExternal( )->SendPacket( client, packet.get( ), len, port );
}

bool Listener::Read( boost::shared_ptr<client_t> client )
{
	if( !client )
	{
		return false;
	}

	unsigned long ip = 0;
	unsigned short port = 0;
	unsigned int len = 0;

	boost::optional<bool> result = client->node->RecvFrom( 0, len, 0, 0 );

	if( !result )
	{
		OutputMessage( "Listener: Error obtaining length of data from client.\n" );

		return false;
	}

	if( len == 0 )
	{
		// No data, no error
		return true;
	}

	boost::shared_ptr<unsigned char> buffer = boost::shared_ptr<unsigned char>( new unsigned char[len] );

	result = client->node->RecvFrom( buffer.get( ), len, &ip, &port );

	if( !result || !*result )
	{
		OutputMessage( "Listener: Failed to receive from client.\n" );

		return false;
	}

	return Parse( client, buffer, len, ip, port );
}

} // namespace
